package utilities;

import javax.sql.DataSource;
import java.io.Serializable;
import java.sql.*;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.logging.Logger;

/**
 * Created with IntelliJ IDEA.
 * User: Jordi
 * Date: 3/01/13
 * Time: 19:23
 * To change this template use File | Settings | File Templates.
 */
public class ConnectorSimple implements DataSource, Serializable {

    protected transient Connection conexion;
    protected Driver driver;
    protected Properties propiedadesConexion = null;
    private String nombreDriver;
    private String dbURL;
    private String nombreUsuario;
    private String password;
    protected String conexionId = "";
    protected boolean debug = false;
    protected String delimitadorPropiedadesConexion = "&";
    /**
     * DataSourceBasicoImpl no tiene capacidad de crear pool
     * y debe ser usado para la prueba (test) o como cliente autonomo
     */
    public ConnectorSimple()  {
        if (Boolean.getBoolean("debug-lwpf") || Boolean.getBoolean("debug-" + getClass().getName())){
            debug = true;
        }
    }
    @Override
    protected ConnectorSimple clone() {
        ConnectorSimple bdsi = new ConnectorSimple();
        try{
            bdsi.setNombreUsuario(nombreUsuario);
            bdsi.setPassword(password);
            bdsi.setPropiedadesConexion(propiedadesConexion);
            bdsi.setDbURL(dbURL);
            bdsi.setDebug(debug);
            bdsi.setNombreDriver(nombreDriver);
            bdsi.setLogWriter(DriverManager.getLogWriter());
            bdsi.setLoginTimeout(DriverManager.getLoginTimeout());
        }catch(SQLException sqle){
            throw new RuntimeException(sqle);
        }
        return bdsi;
    }
    public java.sql.Connection getConnection() throws SQLException{
        if (conexion == null || conexion.isClosed()){
            if (debug) System.out.println("fpuoc ============ " + new java.util.Date() + " " + this.getClass() + "::" + this +"::getConnection()::conexion                    1: " + conexion + " \n");
            try {
                driver = (Driver) Class.forName(getNombreDriver()).newInstance();
                if (this.getPropiedadesConexion() == null || this.getPropiedadesConexion().isEmpty()){
                    conexion = DriverManager.getConnection(getDbURL(), getNombreUsuario(), getPassword());
                }else{
                    conexion = DriverManager.getConnection(getDbURL(), this.getPropiedadesConexion());
                }
            }catch (ClassNotFoundException cnfe) {
                cnfe.printStackTrace();
                throw new RuntimeException(cnfe);
            }catch (SQLException sqle) {
                sqle.printStackTrace();
                throw new RuntimeException(sqle);
            }catch (Exception ex) {
                ex.printStackTrace();
                throw new RuntimeException(ex);
            }
        }
        if (debug) System.out.println("fpuoc ============ " + new java.util.Date() + " " + this.getClass() + "::" + this +"::getConnection()::conexion 2: "
                + conexion + " \n");
        return conexion;
    }
    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        setNombreUsuario(username);
        setPassword(password);
        return getConnection();
    }
    @Override
    public java.io.PrintWriter getLogWriter() throws SQLException {
        return DriverManager.getLogWriter();
    }
    @Override
    public int getLoginTimeout() throws SQLException {
        return DriverManager.getLoginTimeout();
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void setLogWriter(java.io.PrintWriter out) throws SQLException {
        DriverManager.setLogWriter(out);
    }
    @Override
    public void setLoginTimeout(int seconds) throws SQLException {
        DriverManager.setLoginTimeout(seconds);
    }
    public String getConexionId() {
        return conexionId;
    }
    public boolean isDebug() {
        return debug;
    }
    public void setDebug(boolean debug) {
        this.debug = debug;
    }
    public String getNombreDriver() {
        return this.nombreDriver;
    }
    public void setNombreDriver(String driverName) {
        this.nombreDriver = driverName;
    }
    public String getDbURL() {
        return dbURL;
    }
    public void setDbURL(String dbURL) {
        this.dbURL = dbURL;
    }
    public String getNombreUsuario() {
        return nombreUsuario;
    }
    public void setNombreUsuario(String userName) {
        this.nombreUsuario = userName;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public void closeConexion() throws SQLException{
        if (conexion != null){
            conexion.close();
            conexion = null;
        }
    }
    public void setPropiedadesConexion(String propiedadesConexion) {
        StringTokenizer tokenizer = new StringTokenizer(propiedadesConexion, delimitadorPropiedadesConexion, false);
        if (this.propiedadesConexion == null){
            this.propiedadesConexion = new Properties();
        }else{
            this.propiedadesConexion.clear();
        }
        while (tokenizer.hasMoreTokens()){
            String token = tokenizer.nextToken();
            int idx = token.indexOf("=");
            if (idx == -1){
                throw new IllegalArgumentException("DataSourceBasicoImpl::setPropiedadesConexion(String propiedadesConexion): " +
                        propiedadesConexion + "(Formato argumento: <NOMBRE_PROPIEDAD>=<VALOR_PROPIEDAD>[DELIMITADOR]...)");
            }
            this.propiedadesConexion.put(token.substring(0, idx).trim(), token.substring(idx + 1).trim());
        }
    }
    public Properties getPropiedadesConexion() {
        return propiedadesConexion;
    }
    public void setPropiedadesConexion(Properties propiedadesConexion) {
        this.propiedadesConexion = propiedadesConexion;
    }
    public String getDelimitadorPropiedadesConexion() {
        return delimitadorPropiedadesConexion;
    }
    public void setDelimitadorPropiedadesConexion(String delimitadorPropiedadesConexion) {
        this.delimitadorPropiedadesConexion = delimitadorPropiedadesConexion;
    }
    @Override
    public boolean isWrapperFor(Class iface){
        return false;
    }
    @Override
    public Class unwrap(Class iface){
        return null;
    }
}
